﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Transactions;
using Xoohoo.Extensions;
using Xoohoo.Infrastructure;
using Xoohoo.Models;
using Xoohoo.Models.InputModels;
using Xoohoo.Repositories;
using Xoohoo.Utilities.Cryptography;

namespace Xoohoo.Services
{
    public class UserService : IUserService
    {
        private readonly IUserRepository _repository;
        private readonly ICacheModule _cache;
        private readonly XoohooContext _context;
        private readonly IModuleRegistry _modulesLoaded;
        private readonly string _userCacheKeyFormat = "User:{0}";

        public UserService(IUserRepository repository, IModuleRegistry modulesLoaded, XoohooContext context)
        {
            this._repository = repository;
            this._context = context;
            this._modulesLoaded = modulesLoaded;
            this._cache = modulesLoaded.GetModules<ICacheModule>().Last();
        }

        #region IUserService Members
        /// <summary>
        /// 通过用户名获取用户信息
        /// </summary>
        /// <param name="username">用户名</param>
        /// <returns>User</returns>
        public User GetItem(string username)
        {
            return _repository.GetItem(username);
        }
        /// <summary>
        /// 通过用户ID获取用户信息
        /// </summary>
        /// <param name="userID">用户ID</param>
        /// <returns>User</returns>
        public User GetItem(int userID)
        {
            return _repository.GetItem(userID);
        }
        /// <summary>
        /// 通过用户名获取指定状态的用户信息
        /// </summary>
        /// <param name="username">用户名</param>
        /// <returns>User</returns>
        public User GetItem(string username, UserStatus status)
        {
            if (username.IsNullOrWhiteSpace()) return null;

            return _cache!=null?_cache.GetItem<User>(
                _userCacheKeyFormat.FormatWith(username),
                () => _repository.GetItem(username, status),
                null
                ) : _repository.GetItem(username,status);
        }

        public bool IsExists(int userID)
        {
            return _repository.IsExists(userID);
        }

        public bool IsExists(string username)
        {
            return _repository.IsExists(username);
        }

        public bool ValidateUser(int userID, string username)
        {
            return _repository.ValidateUser(userID,username);
        }

        /// <summary>
        /// 用户信息分页
        /// </summary>
        /// <param name="criteria">用户信息搜索条件</param>
        /// <param name="pageingInfo">分页条件</param>
        /// <returns>IPageOfItems<UserBase></returns>
        public IPagedList<UserBasic> GetList(UserSearchCriteria criteria, PagingInfo pageingInfo)
        {
            return _repository.GetList(criteria, pageingInfo);
        }

        public ModelResult SaveAdd(UserInputAdd userInput)
        {
            return Save(userInput);
        }

        public ModelResult SaveEdit(UserInputEdit userInput)
        {
            return Save(userInput);
        }

        public ModelResult Save(UserInput userInput)
        {
            //验证用户名是否被占用
            ModelResult modelResult = ValidateUser(userInput);
            if (!modelResult.IsValid) return modelResult;

            User user;

            using (TransactionScope transaction = new TransactionScope())
            {
                //保存实体
                user = _repository.Save(userInput);

                if (user != null)
                {
                    //保存密码
                    string password = null;
                    if (userInput is UserInputEdit)
                    {
                        password = ((UserInputEdit)userInput).Password;
                    }
                    else if (userInput is UserInputAdd)
                    {
                        password = ((UserInputAdd)userInput).Password;
                    }

                    if (!String.IsNullOrEmpty(password))
                    {
                        SetPassword(user.UserID, password);
                    }

                    //清除缓存
                    if (userInput.UserID.HasValue)
                        invalidateCachedUserForEdit(user);
                    else
                        invalidateCachedUserDependencies(user);
                }

                transaction.Complete();
                return new ModelResult();

            }

        }

        public ModelResult SetPassword(int userID, string password)
        {
            ModelResult modelResult = new ModelResult();
            string passwordSalt = Guid.NewGuid().ToString("N");
            string data = SHA256.Encrypt(password, passwordSalt);
            bool result = _repository.SetPassword(userID, "{0}|{1}".FormatWith(passwordSalt,data));
            if (!result)
                modelResult.Errors.Add("当前用户不存在");
            return modelResult;
        }

        public bool Remove(int userID)
        {
            using (TransactionScope transaction = new TransactionScope())
            {
                bool removedUser = _repository.Remove(userID);
                if (removedUser)
                {
                    User user = new User(userID,null, null, null, null, UserStatus.NotSet, null);
                    if (user != null)
                    {
                        invalidateCachedUserForRemove(user);
                    }
                    transaction.Complete();
                }
                return removedUser;
            }
        }
        /// <summary>
        /// 改变用户状态
        /// </summary>
        /// <param name="userID"></param>
        /// <param name="stauts"></param>
        /// <returns></returns>
        public bool ChangeStatus(int userID, UserStatus status)
        {
            return _repository.ChangeStatus(userID, status);
        }

        public bool SignIn(Func<User> getUser, Action<User> afterSignIn)
        {
            User user = getUser();

            if (user != null&&user.IsAuthenticated)
            {
                //登录成功后将数据缓存
                string cacheKey = _userCacheKeyFormat.FormatWith(user.UserID.ToString());
                _cache.Invalidate(cacheKey);
                _cache.Insert(cacheKey, user);

                if (afterSignIn != null)
                {
                    afterSignIn(user);
                }

                return true;
            }

            return false;
        }

        public void SignOut()
        {
        }

        #endregion

        #region Private Methods

        private void invalidateCachedUserDependencies(User user)
        {
            // UserAuthenticated doesn't have any dependencies
        }

        private void invalidateCachedUserForEdit(User newUser)
        {
            // UserAuthenticated doesn't have any dependencies

            _cache.InvalidateItem(newUser);
        }

        private void invalidateCachedUserForRemove(User user)
        {
            invalidateCachedUserDependencies(user);

            _cache.InvalidateItem(user);
        }
        /// <summary>
        /// 验证用户名是否已经被使用
        /// </summary>
        /// <param name="userInput"></param>
        /// <param name="validationState"></param>
        private ModelResult ValidateUser(UserInput userInput)
        {
            ModelResult modelResult = new ModelResult();
            bool isExists = false;
            if (userInput.UserID.HasValue)//编辑
                isExists = ValidateUser(userInput.UserID.Value, userInput.Username);
            else//添加
                isExists = IsExists(userInput.Username);

            if (isExists)
            {
                modelResult.Errors.Add("用户名【" + userInput.Username + "】已经被使用");
            }
            return modelResult;
        }

        #endregion

    }
}
